/*
 * Created by SharpDevelop.
 * User: Steve
 * Date: 26/10/2006
 * Time: 11:43 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Collections.Generic;
using System.Xml;
using Mokey.ThunderCards.XmlElementNames;
using System.IO;
using Mokey.Common.Forms;
using System.Linq;
using Mokey.Common;

namespace Mokey.ThunderCards.Cards
{
	/// <summary>
	/// Description of CardListFile.
	/// </summary>
	public class CardListFile
	{
		public CardListFile()
        {
            _cards = new List<ThunderCard>();
        }

		public CardListFile(string filePath)
		{
			FilePath = filePath;
			
			XmlDocument cardListXmlDocumnet = new XmlDocument();
			cardListXmlDocumnet.Load(FilePath);
			LoadThunderCardsFromXml(cardListXmlDocumnet);
		}

        public void Save()
        {
            if (string.IsNullOrEmpty(FilePath))
            {
                UIHelper.DisplayErrorMessage("Unable to save file, no file path specified. Try using 'Save As'.");
                return;
            }

            FileInfo filePathInfo = new FileInfo(FilePath);
            SaveMedia(filePathInfo);

            FileStream fs = File.Open(FilePath, FileMode.Create, FileAccess.Write);
            XmlWriter fileToWrite = XmlWriter.Create(fs);
            fileToWrite.WriteStartDocument();
            fileToWrite.WriteStartElement(CardListElements.Root_ThunderCards);
            
            fileToWrite.WriteStartElement(CardListElements.Media_Folder_Name, CardListElements.Root_ThunderCards);
            if (!MediaFolderName.IsTrimNullOrEmpty())
            {
                fileToWrite.WriteValue(MediaFolderName.ToString());
            }
            fileToWrite.WriteEndElement();

            foreach (ThunderCard card in Cards)
            {
                fileToWrite.WriteStartElement(CardListElements.Listing_ThunderCard, CardListElements.Root_ThunderCards);
                WriteThunderCardElement(fileToWrite, CardListElements.Answer, card.Answer);
                WriteThunderCardElement(fileToWrite, CardListElements.AnswerImageFileName, card.AnswerImageFileName);
                WriteThunderCardElement(fileToWrite, CardListElements.Question, card.Question);
                WriteThunderCardElement(fileToWrite, CardListElements.QuestionImageFileName, card.QuestionImageFileName);
                WriteThunderCardElement(fileToWrite, CardListElements.SoundFileName, card.SoundFileName);
                fileToWrite.WriteEndElement();
                fileToWrite.Flush();
            }
            fileToWrite.WriteEndDocument();
            fileToWrite.Flush();
            fileToWrite.Close();
            fs.Close();
        }

        public void SaveAs(string filePath)
        {
            FilePath = filePath;
            Save();
        }

        #region Saving Media

        /// <summary>
        /// Copies the media into a sub directory of where the saved file will be located
        /// </summary>
        /// <param name="filePathInfo">The file path of the xml</param>
        private void SaveMedia(FileInfo filePathInfo)
        {
            string mediaFolderDir = null;
            foreach (ThunderCard cardToProcess in Cards)
            {
                if (!cardToProcess.QuestionImageFileName.IsTrimNullOrEmpty() ||
                    !cardToProcess.AnswerImageFileName.IsTrimNullOrEmpty() ||
                    !cardToProcess.SoundFileName.IsTrimNullOrEmpty())
                {
                    if (mediaFolderDir == null)
                    {
                        mediaFolderDir = EnsureMediaFolder(filePathInfo);
                    }

                    if (!cardToProcess.QuestionImageFileName.IsTrimNullOrEmpty())
                    {
                        cardToProcess.QuestionImageFileName = CopyMediaFileToFolder(mediaFolderDir, cardToProcess.QuestionImageFileName);
                    }

                    if (!cardToProcess.AnswerImageFileName.IsTrimNullOrEmpty())
                    {
                        cardToProcess.AnswerImageFileName = CopyMediaFileToFolder(mediaFolderDir, cardToProcess.AnswerImageFileName);
                    }

                    if (!cardToProcess.SoundFileName.IsTrimNullOrEmpty())
                    {
                        cardToProcess.SoundFileName = CopyMediaFileToFolder(mediaFolderDir, cardToProcess.SoundFileName);
                    }
                }
            }
        }

        private static string CopyMediaFileToFolder(string mediaFolderDirectory, string sourceMediaFile)
        {
            if (sourceMediaFile.Contains("\\"))
            {
                FileInfo sourceFileInfo = new FileInfo(sourceMediaFile);
                int i = 1;
                string destinationMediaFile = mediaFolderDirectory + "\\" + sourceFileInfo.Name;
                while (File.Exists(destinationMediaFile))
                {
                    destinationMediaFile = string.Format("{0}\\{1}_{2}", mediaFolderDirectory, i.ToString(), sourceFileInfo.Name);
                    i++;
                }
                File.Copy(sourceMediaFile, destinationMediaFile);
                FileInfo destinationFileInfo = new FileInfo(destinationMediaFile);
                return destinationFileInfo.Name;
            }
            else
            {
                return sourceMediaFile;
            }
        }
        
        /// <summary>
        /// Makes sure a media folder has been created. Returns the media folder full directory path
        /// </summary>
        /// <param name="filePathInfo">The file path of the xml</param>
        /// <returns></returns>
        private string EnsureMediaFolder(FileInfo filePathInfo)
        {
            if (string.IsNullOrEmpty(MediaFolderName))
            {
                string mediaFolderBaseName = filePathInfo.Name.Replace('.', '_') + "_files";
                MediaFolderName = mediaFolderBaseName;
                int i = 1;
                while (Directory.Exists(filePathInfo.DirectoryName + "\\" + MediaFolderName))
                {
                    MediaFolderName = string.Format("{0}_{1}", mediaFolderBaseName, i);
                    i++;
                }
            }
            
            string mediaFolderDirectory = filePathInfo.DirectoryName + "\\" + MediaFolderName;

            if (!Directory.Exists(mediaFolderDirectory))
            {
                Directory.CreateDirectory(mediaFolderDirectory);
            }

            return mediaFolderDirectory;
        }

        #endregion

		#region Private Fields
		
		private List<ThunderCard> _cards;
        private string _filePath;
        private string _mediaFolderName;
        private string _mediaFolderPath = null;
		
		#endregion
		
		#region Public Fields

        public string MediaFolderName
        {
            get
            {
                return _mediaFolderName;
            }
            private set
            {
                _mediaFolderName = value;
                //we need to regenerate the media folder path if this changes
                _mediaFolderPath = null;
            }
        }

        public string FilePath
        {
            get
            {
                return _filePath;
            }
            private set
            {
                _filePath = value;
                //we need to regenerate the media folder path if this changes
                _mediaFolderPath = null;
            }
        }

		public List<ThunderCard> Cards
		{
			get 
			{
				return _cards;
			}
		}

        public string MediaFolderPath
        {
            get
            {
                if (_mediaFolderPath == null)
                {
                    if (!string.IsNullOrEmpty(FilePath) && !string.IsNullOrEmpty(MediaFolderName))
                    {
                        FileInfo filePathInfo = new FileInfo(FilePath);
                        _mediaFolderPath = string.Format("{0}\\{1}", filePathInfo.Directory, MediaFolderName);
                    }
                    else
                    {
                        _mediaFolderPath = string.Empty; ;
                    }
                }

                return _mediaFolderPath;
            }
        }

		#endregion
		
		#region Private Methods

        private void WriteThunderCardElement(XmlWriter fileToWrite, string tagName, object value)
        {
            fileToWrite.WriteStartElement(tagName, CardListElements.Listing_ThunderCard);
            string valueString = value.ToString();
            if (!string.IsNullOrEmpty(valueString))
            {
                fileToWrite.WriteValue(valueString);
            }
            fileToWrite.WriteEndElement();
        }

		private void LoadThunderCardsFromXml(XmlDocument cardListXmlFile)
		{
			_cards = new List<ThunderCard>();
            if (cardListXmlFile.DocumentElement.ChildNodes != null)
            {
                foreach (XmlNode thunderCardNode in cardListXmlFile.DocumentElement.ChildNodes)
                {
                    if (thunderCardNode.LocalName.ToLower() == CardListElements.Media_Folder_Name.ToLower())
                    {
                        MediaFolderName = thunderCardNode.InnerText;
                    }
                    else if (thunderCardNode.LocalName.ToLower() == CardListElements.Listing_ThunderCard.ToLower())
                    {
                        _cards.Add(LoadThunderCard(thunderCardNode));
                    }
                }
            }
		}
		
		private ThunderCard LoadThunderCard(XmlNode thunderCardNode)
		{
			XmlElement question = thunderCardNode[XmlElementNames.CardListElements.Question];
			XmlElement answer = thunderCardNode[XmlElementNames.CardListElements.Answer];
			XmlElement questionImageFile = thunderCardNode[XmlElementNames.CardListElements.QuestionImageFileName];
			XmlElement answerImageFile = thunderCardNode[XmlElementNames.CardListElements.AnswerImageFileName];
			XmlElement soundeFile = thunderCardNode[XmlElementNames.CardListElements.SoundFileName];
			ThunderCard cardToLoad = new ThunderCard(
			                                         (question == null)? null : question.InnerText,
			                                         (answer == null)? null : answer.InnerText,
			                                         (questionImageFile == null)? null : questionImageFile.InnerText.Trim(),
			                                         (answerImageFile == null)? null : answerImageFile.InnerText.Trim(),
			                                         (soundeFile == null)? null : soundeFile.InnerText.Trim()
			                                        );
			return cardToLoad;
		}
		
		#endregion
		
	}
}
